package engine

import (
	"errors"
	"fmt"
)

var precedence = map[string]int{"+":10,",":100}

type Express interface {
	toString() string
}

type LogicExprAST struct {
	Val string
}

func (l *LogicExprAST)toString() string{
	return fmt.Sprintf("LogicExprAST:%s", l.Val)
}

type ExprASTNode struct {
	ExprList []*Express
	Child Express
}

func (e *ExprASTNode)toString() string{
	return fmt.Sprintf("BinaryExprAST:")
}

type AST struct {
	Tokens []*Token
	source string
	currToken *Token
	currIndex int
	depth int
	Err error
}

func NewAST(tokens []*Token, str string)*AST{
	a := &AST{
		Tokens: tokens,
		source: str,
	}
	if a.Tokens == nil || len(a.Tokens) == 0 {
		a.Err = errors.New("Empty Token")
	} else{
		a.currIndex =0
		a.currToken = a.Tokens[0]
	}
	return a
}

func (a *AST)ParseExpression() *Express {
	a.depth++
	expr := a.parsePrimary()

	return a.parseBinOpRHS(0, expr)

}

func (a *AST)getNextToken() *Token {
	a.currIndex++
	if a.currIndex < len(a.Tokens){
		a.currToken = a.Tokens[a.currIndex]
		return a.currToken
	}
	return nil
}
func (a *AST)getTokenPrecedence() int{
	if p, ok := precedence[a.currToken.Val];ok{
		return p
	}
	return -1
}

func (a *AST)parseLogicExpr() *Express {
	l := &LogicExprAST{Val: a.currToken.Val}
	a.getNextToken()
	return l
}


func (a *AST)*Express {
	switch a.currToken.Type {
	case LogicExpr:
		return a.parseLogicExpr()
	case Operator:
		// 处理（）
		if a.currToken.Val == "(" {
			// 找到"("后， 即立刻获取下一个字符词组
			a.getNextToken()
			// 再次调用ParseExpression，项当于把()里的内容，放到下一次节点处理
			expr := a.ParseExpression()
			if expr == nil{
				return nil
			}
			// 处理完()里的内容 ，需要查找下一位字符词组
			//a.getNextToken()
			if a.currToken.Val != ")"{
				a.Err = errors.New(fmt.Sprintf("需要 ’）‘，但是找到了%s\n", a.currToken.Val))
				return nil
			}
			a.getNextToken()
			return expr
		}else {
			return a.parseLogicExpr()
		}
	default:
		return nil
	}
}


func (a *AST)parseBinOpRHS(execPrecedence int, ln *Express) Express{

	//for {
	//	tokenPrecedence := a.getTokenPrecedence()
	//
	//	if tokenPrecedence < execPrecedence{
	//		return ln
	//	}
	//	binOp := a.currToken.Val
	//	if a.getNextToken() == nil{
	//		return ln
	//	}
	//	rn := a.parsePrimary()
	//	nextPrecedence := a.getTokenPrecedence()
	//	if tokenPrecedence < nextPrecedence{
	//		rn = a.parseBinOpRHS(tokenPrecedence+1, rn)
	//		if rn == nil{
	//			return nil
	//		}
	//	}
	//	ln = BinaryExprAST{
	//		Operator: binOp,
	//		LeftNode: ln,
	//		RightNode: rn,
	//	}
	//}
	topbe := &ExprASTNode{}
	be := &ExprASTNode{}
	topbe.Child = be
	for {
		currOp := a.currToken.Val
		if currOp == ","{
			//be.Operator = currOp
			be.ExprList = append(be.ExprList, ln)
		} else {
			expr := a.ParseExpression()
			topbe.ExprList = append(topbe.ExprList, expr)
		}
		if a.getNextToken() == nil{
			return nil
		}
		rn := a.parsePrimary()
	}
}